package eteam.aps.service.impl;

import eteam.aps.common.component.LoginUserRedisService;
import eteam.aps.common.entity.ParentEntity;
import eteam.aps.common.exceptions.BusinessException;
import eteam.aps.common.helper.Helper;
import eteam.aps.mapper.MocoRdersBordyMapper;
import eteam.aps.mapper.MocoRdersMapper;
import eteam.aps.mapper.ProcessMaterialsMapper;
import eteam.aps.mapper.ProcessMaterialsPreserveMapper;
import eteam.aps.model.dto.ProcessMaterialsDto;
import eteam.aps.model.dto.ProcessPreserveDto;
import eteam.aps.model.entity.MocoRders;
import eteam.aps.model.entity.MocoRdersBordy;
import eteam.aps.model.entity.ProcessMaterials;
import eteam.aps.model.entity.ProcessMaterialsPreserve;
import eteam.aps.model.vo.moco_rders.MocoRdersDisplayVo;
import eteam.aps.model.vo.process_materials.ProcessMaterialsShowVo;
import eteam.aps.model.vo.process_materials.ProcessMaterialsVo;
import eteam.aps.service.ProcessMaterialsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 工艺物料 业务层 实现类
 *
 * @author LiuLei
 */
@Service
public class ProcessMaterialsServiceImpl implements ProcessMaterialsService {

    @Autowired
    private ProcessMaterialsMapper processMaterialsMapper;

    @Autowired
    private ProcessMaterialsPreserveMapper processMaterialsPreserveMapper;

    @Autowired
    private MocoRdersBordyMapper mocoRdersBordyMapper;

    @Autowired
    private MocoRdersMapper mocoRdersMapper;

    @Autowired
    private LoginUserRedisService loginUserRedisService;

    /**
     * 根据任务列表 生成工序
     *
     * @param invCode 产品编号
     * @param mocCode 任务编号
     * @return 工序集合
     */
    @Transactional
    public List<ProcessMaterials> getPMListByMc(String invCode, String mocCode) throws Exception {
        Map<String, Object> mc = new HashMap<>(4);
        mc.put("invCode", invCode);
        mc.put("mocCode", mocCode);
        mc.put("fState", ParentEntity.FSTATE_DELETED);
        mc.put("sort", "FSortSeq");
        List<MocoRders> byMcPnLis = mocoRdersMapper.getByMcPnLis(mc);
        // 工单不存在
        if (byMcPnLis.isEmpty()) throw new BusinessException(HttpStatus.BAD_REQUEST, "暂无数据！");
        // 存在工单
        mc.put("modId", byMcPnLis.stream().map(MocoRders::getfMoId).collect(Collectors.toList()));
        // 根据序号排序
        List<MocoRdersBordy> byMoList = mocoRdersBordyMapper.getByMoList(mc);
        List<ProcessMaterials> proMatList = new LinkedList<>();
        String fuserid = loginUserRedisService.getUser().getFuserid();
        for (MocoRders mocoRders : byMcPnLis) {
            BigDecimal qty = mocoRders.getfQty();
            for (MocoRdersBordy data : byMoList) {
                ProcessMaterials processMaterials = new ProcessMaterials(
                        mocoRders.getfMocCode(), // 任务令
                        data.getfSortSeq(), // 序号
                        data.getfInvCode(), // 物料编号
                        data.getfInvName(), // 物料名称
                        data.getfStdRemark(), // 物料型号
                        null, // 扫描工序
                        null, // 工序名称
                        data.getfQty().divide(qty, 4).toString() // 单套数量
                );
                Helper.setDefaultAddValue(processMaterials, fuserid);
                proMatList.add(processMaterials);
            }
        }
        // 执行保存
        batchSaveProcessMaterials(proMatList);
        return proMatList;
    }

    @Transactional
    public int batchSaveProcessMaterials(List<ProcessMaterials> list) {
        if (list.isEmpty()) return 0;
        return processMaterialsMapper.batchSaveProcessMaterials(list);
    }

//    @Override
//    public List<MocoRdersDisplayVo> getByMoList(String invCode, String mocCode) throws Exception {
//        Map<String, Object> map = new HashMap<>(4);
//        map.put("fState", ParentEntity.FSTATE_DELETED);
//        if (Helper.isNotEmpty(invCode)) map.put("invCode", invCode);
//        if (Helper.isNotEmpty(mocCode)) map.put("mocCode", mocCode);
//        // 根据 产品查询 工序
//        map.put("sort", "FSortSeq");
//        // 产品信息
//        List<MocoRdersVo> byMcPnList = mocoRdersMapper.getByMcPnList(map);
//        if (byMcPnList.isEmpty()) {
//            List<MocoRders> mocoRdersList = U8Api.getArrivalVouch(invCode, mocCode);
//            if (mocoRdersList.isEmpty()) throw new BusinessException(HttpStatus.BAD_REQUEST, "暂无数据");
//            // 保存工单信息
//            int save = mocoRdersMapper.batchSave(mocoRdersList);
//            if (save == mocoRdersList.size()) {
//                byMcPnList = mocoRdersList.stream()
//                        .map(data -> BeanUtil.copyProperties(data, MocoRdersVo.class)).collect(Collectors.toList());
//            }
//        }
//        Map<String, MocoRdersVo> mc = new HashMap<>(byMcPnList.size());
//        byMcPnList.forEach(data -> mc.put(data.getMoDId(), data));
//        List<String> modIdLis = byMcPnList.stream().map(MocoRdersVo::getMoDId).collect(Collectors.toList());
//        List<MocoRdersBordyShowVo> byMoList =
//                mocoRdersBordyMapper.getByMoLis(Helper.isEmpty(invCode) ? invCode : byMcPnList.get(0).getInvCode()
//                        , modIdLis);
//        // 设置任务令
//        byMoList.forEach(data -> data.setMocCode(mc.get(data.getMoDId()).getMocCode()));
//        return byMoList;
//    }

    @Override
    public List<MocoRdersDisplayVo> getByMoList(String invCode, String mocCode) throws Exception {
        return null;
    }

    @Override
    public ProcessMaterialsShowVo getPMByInvOrMoc(String invCode, String mocCode) {
        Map<String, Object> map = new HashMap<>(4);
        ProcessMaterialsShowVo processMaterialsShowVo = new ProcessMaterialsShowVo();
        // 任务令 和 产品号都不为空
        if (Helper.isEmpty(invCode) || Helper.isEmpty(mocCode))
            throw new BusinessException(HttpStatus.BAD_REQUEST, "产品编号且工单代号 不能为空!");
        map.put("invCode", invCode);
        map.put("mocCode", mocCode);
        map.put("fState", ParentEntity.FSTATE_DELETED);
        // 根据 产品查询 工序
        map.put("sort", "FSortSeq");
//        // 查询工序
//        List<ProcessMaterialsVo> list = processMaterialsMapper.selPMLis(map);
//        if (list.isEmpty()) {
//            List<ProcessMaterials> pmListByMc = getPMListByMc(invCode, mocCode);
//            pmListByMc.forEach(data -> {
//                ProcessMaterialsVo vo = new ProcessMaterialsVo();
//                BeanUtils.copyProperties(data, vo);
//                list.add(vo);
//            });
//        }
        processMaterialsShowVo.setProcessMaterialsList(processMaterialsMapper.selPMLis(map));
        // 查询产品工序
        processMaterialsShowVo.setProcessMaterialsPreserveList
                (processMaterialsPreserveMapper.selPmpByInv(map));
        return processMaterialsShowVo;
    }

    @Override
    public List<ProcessMaterialsVo> getPMByInv(String invCode) {
        if (Helper.isEmpty(invCode)) throw new BusinessException(HttpStatus.BAD_REQUEST, "产品编号不能为空!");
        Map<String, Object> map = new HashMap<>(3);
        // 产品号都不为空
        map.put("invCode", invCode);
        map.put("fState", ParentEntity.FSTATE_DELETED);
        // 根据 产品查询 工序
        map.put("sort", "FSortSeq");
        return processMaterialsPreserveMapper.selPmpByInv(map);
    }

    @Override
    public List<ProcessMaterialsVo> getPMByMoc(String mocCode) {
        Map<String, Object> map = new HashMap<>(3);
        // 任务令不为空
        if (Helper.isEmpty(mocCode))
            throw new BusinessException(HttpStatus.BAD_REQUEST, "任务令不能为空!");
        map.put("mocCode", mocCode);
        map.put("fState", ParentEntity.FSTATE_DELETED);
        // 根据 产品查询 工序
        map.put("sort", "FSortSeq");
        return processMaterialsMapper.selPMLis(map);
    }

//
//    @Override
//    @Transactional
//    public ProcessMaterialsShowVo reWriteMocInfo(ProcessMaterialsDto pmd) {
//        ProcessMaterialsShowVo pms = new ProcessMaterialsShowVo();
//        // 获取任务令 工序信息
//        List<ProcessMaterialsVo> pml = pmd.getProcessMaterialsList();
//        // 任务令 物料编号
////        List<String> pmlInvLis = pml.stream().map(ProcessMaterialsVo::getfInvCode).collect(Collectors.toList());
//        // 获取产品 工序信息
//        List<ProcessMaterialsVo> pmlm = pmd.getProcessMaterialsPreserveList();
//        // 准备一个map 存储产品 物料编号 和 产品之间的关系
//        Map<String, ProcessMaterialsVo> map = new HashMap<>();
//        pmlm.forEach(data -> map.put(data.getfInvCode(), data));
////        // 删除原来任务令存在的物料信息
////        if (!pmlInvLis.isEmpty()) processMaterialsMapper.btachDelByInvs(pmlInvLis);
//        List<ProcessMaterials> list = new LinkedList<>();
//        // 遍历任务 物料编号  在根据产品物料编号 获取修改的产品信息
//        for (ProcessMaterialsVo materialsVo : pml) {
//            ProcessMaterialsVo materials = map.get(materialsVo.getfInvCode());
//            ProcessMaterials processMaterials = new ProcessMaterials(
//                    materialsVo.getfMocCode(), // 任务号
//                    materials.getfSortSeq(), // 序号
//                    materials.getfInvCode(), // 物料编号
//                    materials.getFclnvName(), // 物料名称
//                    materials.getFclnvStd(), // 物料型号
//                    materials.getfScaPro(), // 扫描工序
//                    materials.getfProName(), // 工序名称
//                    materials.getfQty() // 单套数量
//            );
//            Helper.setDefaultAddValue(processMaterials, loginUserRedisService.getUser().getFuserid());
//            list.add(processMaterials);
//        }
//        // 保存
//        int save = processMaterialsMapper.batchSaveProcessMaterials(list);
//        if (save == list.size()) {
//            // 查询 产品维护信息
//            HashMap<String, Object> pm = new HashMap<>(3);
//            pm.put("mocCode", pmd.getMocCode());
//            pm.put("invCode", pmd.getInvCode());
//            pm.put("fState", ParentEntity.FSTATE_DELETED);
//            pm.put("sort", "FSortSeq");
//            pms.setProcessMaterialsList(processMaterialsMapper.selPMLis(pm));
//            pms.setProcessMaterialsPreserveList(processMaterialsPreserveMapper.selPmpByInv(pm));
//            return pms;
//        }
//        return pms;
//    }

    @Override
    @Transactional
    public ProcessMaterialsShowVo reWriteMocInfo(ProcessMaterialsDto pmd) throws Exception {
        ProcessMaterialsShowVo pms = new ProcessMaterialsShowVo();
        // 获取任务令 工序信息
        List<ProcessMaterialsVo> pml = pmd.getProcessMaterialsList();
        // 获取该任务下的物料编号
        HashSet<String> invLis = new HashSet<>(pml.size());
        pml.forEach(data -> invLis.add(data.getfInvCode()));
        // 获取产品 工序信息
        List<ProcessMaterialsVo> pmlm = pmd.getProcessMaterialsPreserveList();
        // 过滤出 产品编号存在于任务工序之中 并且产品工序和工序名称 都不为空的数据 的产品工序列表
        pmlm = pmlm.stream().filter(data -> invLis.contains(data.getfInvCode())
                && Helper.isNotEmpty(data.getfProName())
                && Helper.isNotEmpty(data.getfScaPro())).collect(Collectors.toList());
        // 产品工序过滤不为空
        if (!pmlm.isEmpty()) {
            // 存储要修改的任务工序信息
            List<ProcessMaterialsVo> list = new LinkedList<>();
            // 准备一个map 任务物料编号 和 任务之间的关系
            Map<String, ProcessMaterialsVo> map = new HashMap<>();
            // 填充map
            pml.forEach(data -> map.put(data.getfInvCode(), data));
            for (ProcessMaterialsVo materialsVo : pmlm) {
                ProcessMaterialsVo vo = map.get(materialsVo.getfInvCode());
                Helper.setEmptyWithNull(materialsVo);
                // 工序名称
                vo.setfProName(materialsVo.getfProName());
                // 工序编号
                vo.setfScaPro(materialsVo.getfScaPro());
                vo.setfLastModifyTime(LocalDateTime.now());
                vo.setfLastModifyUserId(loginUserRedisService.getUser().getFuserid());
                list.add(vo);
            }
            //只要不为空  就批量修改
            if (!list.isEmpty()) {
                processMaterialsMapper.batchUpdate(list);
            }
        }
        // 查询 产品维护信息
        HashMap<String, Object> pm = new HashMap<>(4);
        pm.put("mocCode", pmd.getMocCode());
        pm.put("invCode", pmd.getInvCode());
        pm.put("fState", ParentEntity.FSTATE_DELETED);
        pm.put("sort", "FSortSeq");
        pms.setProcessMaterialsList(processMaterialsMapper.selPMLis(pm));
        pms.setProcessMaterialsPreserveList(processMaterialsPreserveMapper.selPmpByInv(pm));
        return pms;
    }

//    @Override
//    @Transactional
//    public ProcessMaterialsShowVo reWriteInvInfo(ProcessMaterialsDto pmd) {
//        ProcessMaterialsShowVo pms = new ProcessMaterialsShowVo();
//        // 获取任务工序列表
//        List<ProcessMaterialsVo> pml = pmd.getProcessMaterialsList();
//        // 产品编号列表 （从当前任务里面获取）
//        List<String> pmplInvLis = pml.stream().map(ProcessMaterialsVo::getfInvCode).collect(Collectors.toList());
//        // 产品有工序时 才批量删除产品
//        if (!pmd.getProcessMaterialsPreserveList().isEmpty()) {
//            processMaterialsPreserveMapper.btachDelByInvs(pmplInvLis);
//        }
//        List<ProcessMaterialsPreserve> list = new LinkedList<>();
//        for (ProcessMaterialsVo materialsVo : pml) {
//            ProcessMaterialsPreserve processMaterialsPreserve = new ProcessMaterialsPreserve(
//                    materialsVo.getfSortSeq(), // 序号
//                    materialsVo.getfInvCode(), // 物料编号
//                    materialsVo.getFclnvName(), // 物料名称
//                    materialsVo.getFclnvStd(), // 物料型号
//                    materialsVo.getfScaPro(), // 扫描工序
//                    materialsVo.getfProName(), // 工序名称
//                    materialsVo.getfQty() // 单套数量
//            );
//            Helper.setDefaultAddValue(processMaterialsPreserve, loginUserRedisService.getUser().getFuserid());
//            list.add(processMaterialsPreserve);
//        }
//        // 保存
//        int save = 0;
//        // 任务工序维护 不为空 就批量保存
//        if (!list.isEmpty()) save = processMaterialsPreserveMapper.batchInsert(list);
//        if (save == list.size()) {
//            // 查询 产品维护信息
//            HashMap<String, Object> map = new HashMap<>(2);
//            map.put("invCode", pmd.getInvCode());
//            map.put("sort", "FSortSeq");
//            pms.setProcessMaterialsPreserveList(processMaterialsPreserveMapper.selPmpByInv(map));
//            pms.setProcessMaterialsList(pmd.getProcessMaterialsList());
//            return pms;
//        }
//        return pms;
//    }

    @Override
    @Transactional
    public ProcessMaterialsShowVo reWriteInvInfo(ProcessMaterialsDto pmd) throws Exception {
        ProcessMaterialsShowVo pms = new ProcessMaterialsShowVo();
        // 获取任务工序列表
        List<ProcessMaterialsVo> pml = pmd.getProcessMaterialsList();
        // 过滤出 任务编号存在于产品工序集合中 并且产品工序和工序名称 都不为空的数据 的任务工序列表
        pml = pml.stream().filter(data ->
//                set.contains(data.getfInvCode()) &&
                Helper.isNotEmpty(data.getfProName())
                        && Helper.isNotEmpty(data.getfScaPro())).collect(Collectors.toList());
        if (!pml.isEmpty()) { // 只要是任务工序不为空 就要修改产品工序信息
            String fuserid = loginUserRedisService.getUser().getFuserid();

            // 存储需要修改的产品工序信息
            List<ProcessMaterialsPreserve> list = new LinkedList<>();
            // 保存任务中 要修改产品的编号
            for (ProcessMaterialsVo materialsVo : pml) {
                ProcessMaterialsPreserve processMaterialsPreserve = new ProcessMaterialsPreserve(
                        pmd.getInvCode(), // 产品编号
                        materialsVo.getfSortSeq(), // 序号
                        materialsVo.getfInvCode(), // 物料编号
                        materialsVo.getFclnvName(), // 物料名称
                        materialsVo.getFclnvStd(), // 物料型号
                        materialsVo.getfScaPro(), // 扫描工序
                        materialsVo.getfProName(), // 工序名称
                        materialsVo.getfQty() // 单套数量
                );
                Helper.setDefaultAddValue(processMaterialsPreserve, fuserid);
                list.add(processMaterialsPreserve);
            }
            // 获取工单工序信息
            List<ProcessMaterialsVo> preserveList = pmd.getProcessMaterialsPreserveList();
            // 获取产品信息
//            List<String> pmLis = new ArrayList<>(preserveList.size());
            // 查询出当前产品的信息工序维护
            Map<String, Object> map = new HashMap<>(3);
            map.put("mocCode", pmd.getMocCode());
            map.put("fState", ParentEntity.FSTATE_DELETED);
            map.put("sort", "FSortSeq");
            List<ProcessMaterialsVo> voList = processMaterialsMapper.selPMLis(map);
            // 批量修改的部分
            List<ProcessMaterialsVo> batchUpdate = new LinkedList<>();
            // 过滤出 产品工序编号和工序名称都不为空的工单维护列表
            List<ProcessMaterialsVo> collect = pmd.getProcessMaterialsList().stream().filter(data -> Helper.isNotEmpty(data.getfScaPro())
                    && Helper.isNotEmpty(data.getfProName())).collect(Collectors.toList());
            for (ProcessMaterialsVo processMaterialsVo : collect) {
                // 数据库原数数据  进行对比
                for (ProcessMaterialsVo materialsVo : voList) {
                    // 物料编号相同
                    if (processMaterialsVo.getfInvCode().equals(materialsVo.getfInvCode())) {
                        // 只要工序编号和工序名称不一致 就添加到修改集合
                        if (!processMaterialsVo.getfScaPro().equals(materialsVo.getfScaPro()) ||
                                !processMaterialsVo.getfProName().equals(materialsVo.getfProName())) {
                            Helper.setEmptyWithNull(materialsVo);
                            materialsVo.setfScaPro(processMaterialsVo.getfScaPro());
                            materialsVo.setfProName(processMaterialsVo.getfProName());
                            materialsVo.setfLastModifyTime(LocalDateTime.now());
                            materialsVo.setfLastModifyUserId(fuserid);
                            batchUpdate.add(materialsVo);
                            // 找到了就退出
                            break;
                        }
                    }
                }
            }
            // 不为空 就批量修改工单工序维护信息
            if (!batchUpdate.isEmpty()) processMaterialsMapper.batchUpdate(batchUpdate);
            // 批量删除原来的 todo
            if (Helper.isNotEmpty(pmd.getInvCode())) processMaterialsPreserveMapper.btachDelByInvs(pmd.getInvCode());
            // 批量添加产品工序信息
            if (!list.isEmpty()) processMaterialsPreserveMapper.batchInsert(list);
        }
        // 查询 产品维护信息
        HashMap<String, Object> map = new HashMap<>(3);
        map.put("invCode", pmd.getInvCode());
        map.put("mocCode", pmd.getMocCode());
        map.put("fState", ParentEntity.FSTATE_DELETED);
        map.put("sort", "FSortSeq");
        pms.setProcessMaterialsPreserveList(processMaterialsPreserveMapper.selPmpByInv(map));
        pms.setProcessMaterialsList(processMaterialsMapper.selPMLis(map));
        return pms;
    }

    @Override
    @Transactional
    public int rmInvInfo(String fId) {
        if (Helper.isEmpty(fId)) throw new BusinessException(HttpStatus.BAD_REQUEST, "编号不能为空！");
        List<String> list = Arrays.asList(fId.split(","));
        return processMaterialsPreserveMapper.delete(list);
    }

    @Override
    @Transactional
    public int rmMocInfo(String fId) {
        if (Helper.isEmpty(fId)) throw new BusinessException(HttpStatus.BAD_REQUEST, "编号不能为空！");
        List<String> list = Arrays.asList(fId.split(","));
        return processMaterialsMapper.delete(list);
    }

    @Override
    @Transactional
    public int modInvInfo(ProcessPreserveDto processPreserveDto) throws Exception {
        Helper.setEmptyWithNull(processPreserveDto);
        processPreserveDto.setModifyUserId(loginUserRedisService.getUser().getFuserid());
        processPreserveDto.setModifyTime(LocalDateTime.now());
        return processMaterialsPreserveMapper.update(processPreserveDto);
    }

    @Override
    @Transactional
    public int modMocInfo(ProcessPreserveDto processPreserveDto) throws Exception {
//        Helper.setEmptyWithNull(processPreserveDto);
        processPreserveDto.setModifyUserId(loginUserRedisService.getUser().getFuserid());
        processPreserveDto.setModifyTime(LocalDateTime.now());
        return processMaterialsMapper.update(processPreserveDto);
    }
}